import { defineStore } from 'pinia';
import { getToken, removeToken, setToken } from '../utils/token-utils';
import {ElMessage} from 'element-plus'
import {allAsyncRoutes, anyRoute, staticRoutes} from '@/router/routes'
import type {reqUserInfoReturnType , reqLoginParamType} from '@/api/userInfo'
import {requestLogin,requestUserInfo,requestLogOut} from '@/api/userInfo'
import type { RouteRecordRaw } from 'vue-router';
import cloneDeep from "lodash/cloneDeep";
import router from "@/router";
//1.过滤动态路由中,需要展示的路由菜单,并收集起来(返回出去),接受两个参数 1. 完整的动态路由数组 2. 当前用户信息的routes
function filterAsyncRoutes(
  allAsyncRoutes: RouteRecordRaw[],
  routeNames: string[]
) {
  return allAsyncRoutes.filter((item) => {
    if (routeNames.includes(item.name as string)) {
      //符合条件的item中可能有二级路由,再次判断(递归!!!!!)
      if (item.children && item.children.length) {
        //此时当前一级路由已经顺利通过检测了,但是还是要看它内部的二级路由是否符合,
        //把item.children拿进来判断,最后得到过滤结果之后,直接替换item.children
        item.children = filterAsyncRoutes(
          item.children as RouteRecordRaw[],
          routeNames
        );
      }
      return true;
    }
  });
}

//2.把根据用户信息过滤出来的动态路由数组，和任意路由全部放入静态路由中
function addRoutes(routes: RouteRecordRaw[]) {
  //router只有addRoute方法，所以我们需要遍历动态路由依次插入
  routes.forEach((item) => {
    //因为此时router已经作用于app应用实例上了，再直接去修改staticRoutes是不管用的（只能修改菜单）
    //所以我们需要使用router的addRoute给已经注册的路由器添加新的路由
    router.addRoute(item);
  });
}

//3.封装一个退出登录后 对动态路由的清理
function resetRoutes(staticRoutes: RouteRecordRaw[]) {
  //退出登录的时候，把路由器中的路由全部清理掉
  // 获取所有 路由记录的完整列表
  const routes = router.getRoutes();
  //遍历routes清理路由
  routes.forEach((item) => {
    if (item.name) {
      router.removeRoute(item.name);
    }
  });
  //清理完所有的路由，然后把静态路由再插入回去
  addRoutes(staticRoutes);
}

//小store仓库state数据类型
export interface UserInfoState{
    token:string,
    userInfo:reqUserInfoReturnType,
    menuRoutes:RouteRecordRaw[]
}

/**
 * 用户信息
 * @methods setUserInfos 设置用户信息
 */
export const useUserInfoStore = defineStore('userInfo', {

	state: (): UserInfoState => ({
    token: getToken() as string || '',
    userInfo:{
      routes: [],
      buttons: [],
      roles: [],
      name: '',
      avatar: ''
    },
    //静态路由表，侧边栏拿这个表遍历生成侧边栏元素
    menuRoutes: staticRoutes
  }),

	actions: {
    //登录请求函数
    async login (loginParam:reqLoginParamType) {
      try {
        //发送登录请求
        const result = await requestLogin(loginParam)
        //获取token
        this.token = result.token
        //设置token到本地，数据持久化
        setToken(this.token)
      } catch (e) {
        //请求失败，谁调用谁处理
        return Promise.reject(e)
      }
    },
    //获取用户信息请求函数
    async getInfo () {
      try {
        //发送获取用户信息请求
        const result = await requestUserInfo()
        //获取用户信息
        this.userInfo = result
        //1.获取用户信息后,立马检测动态路由中哪些是符合权限的,过滤出来
        const userAscynRoutes = filterAsyncRoutes(
          cloneDeep(allAsyncRoutes),
          result.routes
        );

        //2. 把过滤出来的动态路由插入到路由器中
        addRoutes(userAscynRoutes.concat(anyRoute));

        //3. 修改静态路由，让菜单栏也进行更新
        this.menuRoutes = staticRoutes.concat(userAscynRoutes, anyRoute);
      } catch (e) {
        return Promise.reject(e)
      }  
    },
    //退出登录请求函数
    async getLogOut() {
      try {
        //发送请求
        await requestLogOut()
        //重置信息
        this.reset()
         //退出后 清理路由
         resetRoutes(staticRoutes);
      } catch (e) {
        return Promise.reject(e)
      }
    },
    //重置信息
    reset () {
      // 删除local中保存的token
      removeToken()
      // 提交重置用户信息的mutation
      this.token = ''
      this.userInfo = {
        routes: [],
        buttons: [],
        roles: [],
        name: '',
        avatar: ''
      }
    },
	},
});
